﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using InternetThermostat.Models;

namespace InternetThermostat.Tests.UnitTests
{
    [TestClass]
    public class UnitTests
    {
        Dictionary dictionary;

        [TestInitialize]
        public void Initialize()
        {
            dictionary = new Dictionary();

            // Weekdays
            for (var day = DayOfWeek.Monday; day < DayOfWeek.Friday; day++)
            {
                var morningWakeUp = new DayTime { Day = day, Hour = 7, Minute = 30 };
                var morningLeave = new DayTime { Day = day, Hour = 9, Minute = 00 };
                var eveningArrive = new DayTime { Day = day, Hour = 5 + 12, Minute = 30 }; ;
                var eveningSleep = new DayTime { Day = day, Hour = 11 + 12, Minute = 30 };

                Schedule.WeeklySchedule.Add(morningWakeUp, 68);
                Schedule.WeeklySchedule.Add(morningLeave, 58);
                Schedule.WeeklySchedule.Add(eveningArrive, 68);
                Schedule.WeeklySchedule.Add(eveningSleep, 60);
            }


            // Sunday
            {
                var morningWakeUp = new DayTime { Day = DayOfWeek.Sunday, Hour = 9, Minute = 30 };
                var eveningSleep = new DayTime { Day = DayOfWeek.Sunday, Hour = 11 + 12, Minute = 30 };

                Schedule.WeeklySchedule.Add(morningWakeUp, 68);
                Schedule.WeeklySchedule.Add(eveningSleep, 60);
            }

            // Sunday
            {
                var morningWakeUp = new DayTime { Day = DayOfWeek.Saturday, Hour = 9, Minute = 30 };
                var eveningSleep = new DayTime { Day = DayOfWeek.Saturday, Hour = 1, Minute = 00 };

                Schedule.WeeklySchedule.Add(morningWakeUp, 68);
                Schedule.WeeklySchedule.Add(eveningSleep, 60);
            }
        }

        [TestCleanup]
        public void Cleanup()
        {
            dictionary = null;

        }



        #region Dictionary Tests

        [TestMethod]
        public void Dictionary_Add_ShouldUpdateCount()
        {
            dictionary.Add(new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 }, 70);
            Assert.AreEqual(1, dictionary.Count);
        }

        [TestMethod]
        public void Dictionary_Add_AddMultipleShouldUpdateCount()
        {
            dictionary.Add(new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 }, 70);
            dictionary.Add(new DayTime { Day = DayOfWeek.Monday, Hour = 2, Minute = 1 }, 70);
            Assert.AreEqual(2, dictionary.Count);
        }

        [TestMethod]
        public void Dictionary_Add_VerifyGotAdded()
        {
            var date = new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 };
            byte temp = 70;

            dictionary.Add(date, temp);

            Assert.IsTrue(dictionary.Contains(date));
            Assert.AreEqual(temp, dictionary[date]);
        }

        [TestMethod]
        public void Dictionary_Change_ShouldChangeValue()
        {
            var date = new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 };
            byte temp = 70;

            dictionary.Add(date, temp);
            Assert.AreEqual(temp, dictionary[date]);


            dictionary[date] = ++temp;
            Assert.AreEqual(temp, dictionary[date]);
        }


        [TestMethod]
        public void Dictionary_Remove_ShouldRemoveItem()
        {
            var date = new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 };
            byte temp = 70;

            dictionary.Add(date, temp);
            Assert.AreEqual(1, dictionary.Count);

            dictionary.Remove(date);
            Assert.AreEqual(0, dictionary.Count);
        }

        [TestMethod]
        public void Dictionary_Remove_ShouldRemoveItem2()
        {
            var date = new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 1 };
            var date2 = new DayTime { Day = DayOfWeek.Monday, Hour = 2, Minute = 1 };
            byte temp = 70;

            dictionary.Add(date, temp);
            dictionary.Add(date2, temp);
            Assert.AreEqual(2, dictionary.Count);

            dictionary.Remove(date);
            Assert.AreEqual(1, dictionary.Count);
        }

        #endregion

        #region Schedule Tests

        [TestMethod]
        public void Schedule_GetNextScheduledTemperature()
        {
            Assert.IsTrue(Schedule.WeeklySchedule.Count != 0);

            var curDateTime = new DateTime(2013, 1, 7, 0, 0, 0);
            var next = Schedule.GetNextScheduledTemperature(curDateTime);
            Assert.AreEqual(68, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Monday, Hour = 7, Minute = 30 }, next.Key);

            curDateTime = new DateTime(2013, 1, 8, 0, 0, 0);
            next = Schedule.GetNextScheduledTemperature(curDateTime);
            Assert.AreEqual(68, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Tuesday, Hour = 7, Minute = 30 }, next.Key);

            curDateTime = new DateTime(2013, 1, 8, 8, 0, 0);
            next = Schedule.GetNextScheduledTemperature(curDateTime);
            Assert.AreEqual(58, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Tuesday, Hour = 9, Minute = 00 }, next.Key);

            curDateTime = new DateTime(2013, 1, 8, 9, 0, 0);
            next = Schedule.GetNextScheduledTemperature(curDateTime);
            Assert.AreEqual(68, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Tuesday, Hour = 5 + 12, Minute = 30 }, next.Key);

            // Wrap around to next week
            curDateTime = new DateTime(2013, 1, 6, 23, 30, 0);
            next = Schedule.GetNextScheduledTemperature(curDateTime);
            Assert.AreEqual(68, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Monday, Hour = 7, Minute = 30 }, next.Key);

        }

        [TestMethod]
        public void Schedule_GetNextOverrideTemperature()
        {
            Schedule.Override.Add(new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 15 }, 50);
            Assert.IsTrue(Schedule.Override.Count != 0);

            var curDateTime = new DateTime(2013, 1, 7, 0, 0, 0);
            var next = Schedule.GetNextOverrideTemperature(curDateTime);
            Assert.AreEqual(50, next.Value);
            Assert.AreEqual(new DayTime { Day = DayOfWeek.Monday, Hour = 1, Minute = 15 }, next.Key);
        } 

        #endregion

        #region DayTime Tests

        [TestMethod]
        public void DayTime_Add()
        {
            DayTime time = new DayTime() { Day = DayOfWeek.Sunday, Hour = 0, Minute = 0 };

            time.Add(59);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Sunday, Hour = 0, Minute = 59 }, time);

            time.Add(1);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Sunday, Hour = 1, Minute = 0 }, time);

            time.Add(60 * 11);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Sunday, Hour = 12, Minute = 0 }, time);

            time.Add(60 * 12 - 1);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Sunday, Hour = 23, Minute = 59 }, time);

            time.Add(1);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Monday, Hour = 0, Minute = 0 }, time);

            time.Add(7 * 24 * 60);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Monday, Hour = 0, Minute = 0 }, time);

            time.Add(30 * 7 * 24 * 60);
            Assert.AreEqual(new DayTime() { Day = DayOfWeek.Monday, Hour = 0, Minute = 0 }, time);
        }

        [TestMethod]
        public void DayTime_EqualNotEqual()
        {
            DayTime time = new DayTime() { Day = DayOfWeek.Sunday, Hour = 0, Minute = 0 };
            DayTime time2 = new DayTime() { Day = DayOfWeek.Sunday, Hour = 0, Minute = 0 };
            DayTime time3 = new DayTime() { Day = DayOfWeek.Sunday, Hour = 0, Minute = 1 };

            Assert.AreEqual(time, time2);
            Assert.IsTrue(time == time2);
            Assert.IsFalse(time != time2);

            Assert.AreNotEqual(time2, time3);
            Assert.IsTrue(time2 != time3);
            Assert.IsFalse(time2 == time3);

        } 

        #endregion

    }
}
